package cn.tedu.charging.order.mqtt;

import cn.tedu.charging.common.pojo.JsonResult;
import cn.tedu.charging.common.pojo.param.ChargingProcessParam;
import cn.tedu.charging.common.pojo.utils.JsonUtils;
import cn.tedu.charging.common.pojo.vo.ChargingProcessVO;
import cn.tedu.charging.order.constant.Constant;
import cn.tedu.charging.order.constant.MqttConstant;
import cn.tedu.charging.order.constant.OrderStatusConstant;
import cn.tedu.charging.order.pojo.param.ChargingResultParam;
import cn.tedu.charging.order.pojo.po.ChargingBillFailPO;
import cn.tedu.charging.order.pojo.po.ChargingBillSuccessPO;
import cn.tedu.charging.order.pojo.po.ChargingProcessPO;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;

@Slf4j
public class MqttConsumer implements MqttCallbackExtended {
    MqttClient mqttClient;
    MqttContext mqttContext;

    public MqttConsumer(MqttClient mqttClient,MqttContext mqttContext) {
        this.mqttClient = mqttClient;
        this.mqttContext = mqttContext;
    }

    @Override
    public void connectComplete(boolean b, String s) {
        log.debug("mqtt-consumer链接成功");
        try {
            mqttClient.subscribe(MqttConstant.TOPIC_CHARGING_RESULT);
            log.debug("连接成功,订阅开始充电-topic:{},成功",MqttConstant.TOPIC_CHARGING_RESULT);
            mqttClient.subscribe(MqttConstant.TOPIC_CHARGING_PROCESS);
            log.debug("连接成功,订阅充电进度-topic:{},成功",MqttConstant.TOPIC_CHARGING_PROCESS);
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void connectionLost(Throwable throwable) {

    }

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        log.debug("MqttConsumer:消息到达:topic-{},message-{}", topic, message);
        if (MqttConstant.TOPIC_CHARGING_RESULT.equals(topic)){
            log.debug("MqttConsumer:开始充电成功消息到达:topic-{},message-{}", topic, message);
            successResult(message);
        } else if (MqttConstant.TOPIC_CHARGING_PROCESS.equals(topic)) {
            log.debug("MqttConsumer:充电进度消息到达:topic-{},message-{}", topic, message);
            handleChargingProcess(message);
        }
    }
    private void handleChargingProcess(MqttMessage message) {
        ChargingProcessParam chargingProcessParam = null;
        try{
            chargingProcessParam = JsonUtils.fromJson(message.toString(), ChargingProcessParam.class);
        }catch (Exception e) {
            log.warn("设备发送的消息格式有问题,请检查!", message);
        }
        log.debug("消息转换成对象,chargingProcessParam-{}",chargingProcessParam);
        //1 调用计价服务获取充电花费
        ChargingProcessVO orderCost = getOrderCost(chargingProcessParam);
        log.debug("通过open-feign的costClient 调用计价服务 计算价格 成功.入参:{},出参:{}",chargingProcessParam,orderCost);

        if (orderCost != null) {
            BigDecimal totalCost = orderCost.getTotalCost();
            //2 保存充电进度
            saveChargingProcess(chargingProcessParam);

            //3 推动给用户充电数据(webSocket)
            syncChargingProcess2User(orderCost);

            //4 查询用户余额 并判断钱够不够
            checkUserBalance(chargingProcessParam.getUserId(),totalCost);

            //5 判断温度 推送告警信息给用户
            checkDeviceStatus(chargingProcessParam.getTemperature());

            //6 判断是否充满 并停止充电 结束订单
            checkChargingStatus(chargingProcessParam.getIsFull());
        }

    }

    //1
    private ChargingProcessVO getOrderCost(ChargingProcessParam chargingProcessParam) {
        JsonResult<ChargingProcessVO> result = mqttContext.getCostClient().calculate(chargingProcessParam);
        if (result != null) {
            ChargingProcessVO data = result.getData();
            if (data != null) {
                return data;
            }
        }
        return null;

    }

    //2
    private void saveChargingProcess(ChargingProcessParam chargingProcessParam) {
        ChargingProcessPO chargingProcessPO = new ChargingProcessPO();
        chargingProcessPO.setId(System.currentTimeMillis());
        BeanUtils.copyProperties(chargingProcessParam,chargingProcessPO);
        mqttContext.getChargingProcessRepository().save(chargingProcessPO);
        log.debug("保存充电进度数据成功:{}",chargingProcessParam);
    }

    //3
    private void syncChargingProcess2User(ChargingProcessVO orderCost) {
        log.debug("同步充电数据到用户手机端:{}",orderCost);
        String json = JsonUtils.toJson(orderCost);
        mqttContext.getWebSocketServer().sendMessage(orderCost.getUserId(),json);
    }

    //4
    private void checkUserBalance(Integer userId, BigDecimal totalCost) {
        JsonResult<BigDecimal> resultUserBalance=mqttContext.getUserClient().getUserBalance(userId);
        if (resultUserBalance != null) {
            BigDecimal userBalance = resultUserBalance.getData();
            if (userBalance.subtract(totalCost).floatValue()<=0){
                log.debug("给用户发送通知,余额不足,停止充电.引导用户进行充值,当前余额:{},订单消费:{}",userBalance,totalCost);
            }
        }
    }

    //5
    private void checkDeviceStatus(float temperature) {
        if (temperature>MqttConstant.A_WARNING){
            log.debug("温度超过:{},给用户发送A类告警,直接停止充电,实际温度:{}",MqttConstant.A_WARNING,temperature);

        }else if (temperature<MqttConstant.B_WARNING){
            log.debug("温度超过:{},给用户发送B类告警,设备不停止充电,让用户选择是否继续充电,实际温度:{}",MqttConstant.B_WARNING,temperature);

        }
    }

    //6
    private void checkChargingStatus(Boolean isFull) {
        if (isFull) {
            log.debug("已经充满,更新订单状态,更新余额");
        }
    }


    private void successResult(MqttMessage message) {
        ChargingResultParam deviceResultParam = null;
        try{
            deviceResultParam = JsonUtils.fromJson(message.toString(), ChargingResultParam.class);
        }catch (Exception e) {
            log.warn("设备发送的消息格式有问题,请检查!", message);
        }
        log.debug("消息转换成对象,chargingResultParam-{}",deviceResultParam);
        if (deviceResultParam != null) {
            //取出充电结果 1 开始成功 2 开始失败
            String result = deviceResultParam.getResult();
            if (Constant.RESULT_START_CHARGING_SUCCESS.equals(result)) {
                //开始充电成功
                log.debug("充电桩开始充电:{}",deviceResultParam);
                //创建订单成功记录
                ChargingBillSuccessPO chargingBillSuccessPO=new ChargingBillSuccessPO();
                chargingBillSuccessPO.setBillId(deviceResultParam.getOrderNo());
                chargingBillSuccessPO.setBillStatus(OrderStatusConstant.ORDER_STATUS_PROGRESS);
                //插入成功订单数据到数据库
                try{
                    mqttContext.getOrderRepository().saveSuccessOrder(chargingBillSuccessPO);
                }catch (Exception e) {
                    log.error("保存成功订单数据失败",e);
                }
                log.debug("保存成功订单数据:{},成功",chargingBillSuccessPO);
            }else {
                log.debug("充电状态开始充电失败,充电桩故障.");
                ChargingBillFailPO chargingBillFailPO=new ChargingBillFailPO();
                chargingBillFailPO.setBillId(deviceResultParam.getOrderNo());
                chargingBillFailPO.setFailDesc("设备自检失败-设备有反应但是无法充电");
                //插入失败订单数据到数据库
                mqttContext.getOrderRepository().saveFailOrder(chargingBillFailPO);
                log.debug("保存失败订单数据:{},成功",chargingBillFailPO);
            }
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        log.debug("MqttConsumer deliveryComplete");
    }
}
